% zhspacing.sty		version 0.4
% Simple macro for typesetting mixed Chinese documents in XeTeX
%	with punctuation space adjustment and prohibitions
% coded by YIN Dian (yindian@ustc)
% Licensed under GPL
% History:	070804	First usable version.
%		070805	Several line breaking bug fixes.
%		070807	\zhinteropenskip changed to 0.6em. \enfont
%			TODO list written.
%		070808	Use macros instead of skips to fit different font size.
%		070809	Tried to use myclass to manage classes, but failed.
%			Then I found it works when \relax is added.
%		070810	Changed skip parameters. Removed \relax, only register
%			non-empty tokens instead. Now it seems to work right.
%			Several bugs fixed. CJK Ext-A/B support added.
%			Added three skip schemes.
%		070812	Fixed font switch bug between CJK Ext-A and Ext-B chars.
%			Obsoleted the use of \enfont.
%		070822	Fixed bug of unbalanced group when using ulem? Cleared
%			XeTeX's pre-defined inter-char tokens. Use seperate
%			font for punctuations. 
%			Deprecated the use of begin/end-groups in LaTeX, in 
%			order to work properly with ulem. Coded zhulem.sty.
%		070823	Use more flexible way to save font. Changed space
%			ignoring mechanism after hanzi to allow \skipenzh added
%			between hanzi and boundary if the next non-space token
%			is a char and is not fullwidth nor in PUA.
%		070824	Enabled automatic skip between math formulas and CJK 
%			chars. Changed skip schemes. Added \zhspacingrevision.
\catcode`\@=11
\ifx\zhs@defined\@undefined
\def\zhs@defined{\relax}
\def\zhspacingrevision{2007.8.24.}
\XeTeXlinebreaklocale="zh"
\XeTeXlinebreakskip=0pt plus 0.2em minus 0.1em
\def\zhnobreak{\nobreak}
\def\simsunskipscheme{% should be fit for sim-xxx fonts
  % my skip
  \def\skipzh{\hskip 0em plus 0.2em minus 0.1em}
  \def\skipenzh{\hskip 0.25em plus 0.15em minus 0.05em}
  \def\skipzhopen{\hskip -0.1em plus 0.1em minus 0.2em}
  \def\skipzhinteropen{\hskip -0.3em plus 0.1em minus 0.1em}
  \def\skipzhlinestartopen{\hskip -0.35em}
  \def\skipzhclose{\hskip -0.1em  plus 0.1em minus 0.2em}
  \def\skipzhinterclose{\hskip -0.3em plus 0.1em minus 0.1em}
  \def\skipzhlineendclose{\hskip -0.35em}
  \def\skipzhjudou{\hskip -0.1em  plus 0.1em minus 0.4em}
  \def\skipzhinterjudou{\hskip -0.3em plus 0.1em minus 0.1em}
  \def\skipzhlineendjudou{\hskip -0.6em}
  % neg
  \def\skipnegzhlinestartopen{\hskip 0.35em}
  \def\skipnegzhlineendclose{\hskip 0.35em}
  \def\skipnegzhlineendjudou{\hskip 0.6em}
}
\def\emptyskipscheme{% just for test use
  % my skip
  \def\skipzh{\hskip 0em plus 0.1em}
  \def\skipenzh{\hskip 0em plus 0.2em}
  \def\skipzhopen{\hskip 0pt}
  \def\skipzhinteropen{\hskip 0pt}
  \def\skipzhlinestartopen{\hskip 0pt}
  \def\skipzhclose{\hskip 0pt}
  \def\skipzhinterclose{\hskip 0pt}
  \def\skipzhlineendclose{\hskip 0pt}
  \def\skipzhjudou{\hskip 0pt}
  \def\skipzhinterjudou{\hskip 0pt}
  \def\skipzhlineendjudou{\hskip 0pt}
  % neg
  \def\skipnegzhlinestartopen{\hskip 0pt}
  \def\skipnegzhlineendclose{\hskip 0pt}
  \def\skipnegzhlineendjudou{\hskip 0pt}
}
\def\haltskipscheme{% should be fit for Adobe opentype fonts with halfwidth alternative enabled
  % my skip
  \def\skipzh{\hskip 0em plus 0.2em minus 0.1em}
  \def\skipenzh{\hskip 0.25em plus 0.15em minus 0.05em}
  \def\skipzhopen{\hskip 0.3em minus 0.3em}
  \def\skipzhinteropen{\hskip 0em plus 0.1em }
  \def\skipzhlinestartopen{\hskip 0em}
  \def\skipzhclose{\hskip 0.3em  minus 0.3em}
  \def\skipzhinterclose{\hskip 0em plus 0.1em}
  \def\skipzhlineendclose{\hskip 0em}
  \def\skipzhjudou{\hskip 0.4em  minus 0.4em}
  \def\skipzhinterjudou{\hskip 0em plus 0.1em}
  \def\skipzhlineendjudou{\hskip 0em}
  % neg
  \def\skipnegzhlinestartopen{\hskip 0em}
  \def\skipnegzhlineendclose{\hskip 0em}
  \def\skipnegzhlineendjudou{\hskip 0em}
}
\simsunskipscheme
%\let\mydbgmessage\message
\def\mydbgmessage#1{}

% font save and restore
\def\zhs@oldf@encoding{}
\def\zhs@oldf@family{}
\def\zhs@oldf@series{}
\def\zhs@oldf@shape{}
\def\zhs@oldf@size{}
\def\zhs@savef@nt#1{%
  \expandafter\xdef\csname zhs@#1f@encoding\endcsname{\f@encoding}%
  \expandafter\xdef\csname zhs@#1f@family\endcsname{\f@family}%
  \expandafter\xdef\csname zhs@#1f@series\endcsname{\f@series}%
  \expandafter\xdef\csname zhs@#1f@shape\endcsname{\f@shape}%
  \expandafter\xdef\csname zhs@#1f@size\endcsname{\f@size}%
}
\def\zhs@restoref@nt#1{%
  \edef\f@encoding{\csname zhs@#1f@encoding\endcsname}%
  \edef\f@family{\csname zhs@#1f@family\endcsname}%
  \edef\f@series{\csname zhs@#1f@series\endcsname}%
  \edef\f@shape{\csname zhs@#1f@shape\endcsname}%
  \edef\f@size{\csname zhs@#1f@size\endcsname}%
  \selectfont
}
\def\zhs@printf@nt#1{%
  \immediate\write16{Font #1 is: \csname zhs@#1f@encoding\endcsname/\csname zhs@#1f@family\endcsname/\csname
  zhs@#1f@series\endcsname/\csname zhs@#1f@shape\endcsname/\csname zhs@#1f@size\endcsname}%
}
\def\zhgroupsavefont{%
  \let\zhs@savefont=\begingroup
  \let\zhs@restorefont=\endgroup
}
\def\zhnfsssavefont{%
  \def\zhs@savefont{\zhs@savef@nt{old}}
  \def\zhs@restorefont{\zhs@restoref@nt{old}}
}
\input usefulmacros.sty
\@ifundefined{LaTeX}{\zhgroupsavefont}{\zhnfsssavefont}

% test CJK char
\input ifcjkchar.sty
\let\zhs@tmpchar\relax
\def\zhs@skipspaces{\futurenonspacelet\zhs@tmpchar\zhs@skipsp@ces}
\def\zhs@skipsp@ces{%
  \expandafter\mydbgmessage\expandafter{\meaning\zhs@tmpchar}%
  \ifcat a\noexpand\zhs@tmpchar % catcode 11
    \ifcjkchar\zhs@tmpchar{}{\skipenzh\relax}%
  \else
    \ifcat !\noexpand\zhs@tmpchar % catcode 12
      \ifcjkchar\zhs@tmpchar{}{\skipenzh\relax}%
    \else
      \ifcat $\noexpand\zhs@tmpchar % catcode 3
        \skipenzh\relax
      \fi
    \fi
  \fi
}
\def\zhs@aftermathskip{%
  \ifnum\lastnodetype=10 % math node
    \skipenzh\relax
  \fi
}
% Character class settings.
\input myclass.sty
% three base classes: boundary, halfwidth and fullwidth
\newclass{boundary}
\setclassnum{boundary}{255}
\newclass{halfwidth}
\newclass{fullwidth}
\setinterclasstoks{boundary}{fullwidth}{\mydbgmessage{^^JZ}\zhs@savefont\zhfont}
\setinterclasstoks{fullwidth}{boundary}{\mydbgmessage{^^Jz}\zhs@restorefont\ignorespaces}
\setinterclasstoks{halfwidth}{fullwidth}{\mydbgmessage{^^JP}\zhs@savefont\zhfont}
\setinterclasstoks{fullwidth}{halfwidth}{\mydbgmessage{^^Jp}\zhs@restorefont}
% derived class alphanum and hanzi
\newclass[halfwidth]{alphanum}
\setclassnum{alphanum}{0}
\newclass[fullwidth]{hanzi}
\setclassnum{hanzi}{1}
\setinterclasstoks{hanzi}{hanzi}{\skipzh\relax}
%\appendinterclasstoks{alphanum}{hanzi}{\mydbgmessage{^^JQ}\skipenzh\relax}
%\prependinterclasstoks{hanzi}{alphanum}{\mydbgmessage{^^Jq}\skipenzh\relax}
\setinterclasstoks{alphanum}{hanzi}{\mydbgmessage{^^JQ}\skipenzh\relax\zhs@savefont\zhfont}
\setinterclasstoks{hanzi}{alphanum}{\mydbgmessage{^^Jq}\zhs@restorefont\skipenzh\relax}
\setinterclasstoks{hanzi}{boundary}{\mydbgmessage{^^Ji}\zhs@restorefont\zhs@skipspaces}
\setinterclasstoks{boundary}{hanzi}{\mydbgmessage{^^JI}\zhs@aftermathskip\zhs@savefont\zhfont}
% derived class from fullwidth
\newclass[fullwidth]{openfw} % ‘, （, etc
\setclassnum{openfw}{2}
\newclass[fullwidth]{closefw} % ’, ）, etc
\setclassnum{closefw}{3}
\newclass[fullwidth]{judou} % ，, 。, etc
\setclassnum{judou}{4}
\newclass[fullwidth]{fwpunct} % extra fullwidth punctuations
\setclassnum{fwpunct}{7}
% open fullwidth punctuation after other characters
\@foreach\class\in{hanzi,fwpunct,alphanum,halfwidth,boundary}\do{%
  \prependinterclasstoks{\class}{openfw}{\mydbgmessage{^^JA1}\allowbreak\skipzhopen\nobreak\skipnegzhlinestartopen\vadjust{}\zhnobreak\skipzhlinestartopen\relax}
}
\setinterclasstoks{openfw}{openfw}{\mydbgmessage{^^JA2}\zhnobreak\skipzhinteropen\relax}
\setinterclasstoks{closefw}{openfw}{\mydbgmessage{^^JA3}\zhnobreak\skipzhlineendclose\allowbreak\skipnegzhlineendclose\skipzhinterclose\skipzhinteropen\skipnegzhlinestartopen\vadjust{}\zhnobreak\skipzhlinestartopen\relax}
\setinterclasstoks{judou}{openfw}{\mydbgmessage{^^JA4}\zhnobreak\skipzhlineendjudou\allowbreak\skipnegzhlineendjudou\skipzhinterjudou\skipzhinteropen\skipnegzhlinestartopen\vadjust{}\zhnobreak\skipzhlinestartopen\relax}
% close fullwidth punctuation before other characters
\@foreach\class\in{hanzi,fwpunct,alphanum,halfwidth,boundary}\do{%
  \prependinterclasstoks{closefw}{\class}{\mydbgmessage{^^JB1}\zhnobreak\skipzhlineendclose\allowbreak\skipnegzhlineendclose\skipzhclose\relax}
}
\setinterclasstoks{closefw}{closefw}{\mydbgmessage{^^JB2}\zhnobreak\skipzhinterclose\relax}
\setinterclasstoks{closefw}{judou}{\mydbgmessage{^^JB3}\zhnobreak\skipzhinterclose\relax}
% judou punctuation before other characters
\@foreach\class\in{hanzi,fwpunct,alphanum,halfwidth,boundary}\do{%
  \prependinterclasstoks{judou}{\class}{\mydbgmessage{^^JC1}\zhnobreak\skipzhlineendjudou\allowbreak\skipnegzhlineendjudou\skipzhjudou\relax}
}
\setinterclasstoks{judou}{closefw}{\mydbgmessage{^^Jb2}\zhnobreak\skipzhinterjudou\relax}
\setinterclasstoks{judou}{judou}{\mydbgmessage{^^JC2}\zhnobreak\skipzhinterjudou\relax}
% open fullwidth punctuation before other characters
\@foreach\class\in{hanzi,fwpunct,alphanum,halfwidth,boundary,closefw,judou}\do{%
  \prependinterclasstoks{openfw}{\class}{\mydbgmessage{^^Ja}\zhnobreak}
}
% close fullwidth punctuation after other characters
\@foreach\class\in{hanzi,fwpunct,alphanum,halfwidth,boundary}\do{%
  \prependinterclasstoks{\class}{closefw}{\mydbgmessage{^^Jb}\zhnobreak}
}
% judou punctuation after other characters
\@foreach\class\in{hanzi,fwpunct,alphanum,halfwidth,boundary}\do{%
  \prependinterclasstoks{\class}{judou}{\mydbgmessage{^^Jc}\zhnobreak}
}
% punctuation font change
\@foreach\class\in{openfw,closefw,judou,fwpunct}\do{%
  \appendinterclasstoks{hanzi}{\class}{\zhpunctfont}
  \appendinterclasstoks{\class}{hanzi}{\zhfont}
}
% CJK Ext-A/B support
\newclass[hanzi]{cjkexta}
\setclassnum{cjkexta}{8}
\newclass[hanzi]{cjkextb}
\setclassnum{cjkextb}{9}
\@foreach\class\in{hanzi,fwpunct,openfw,closefw,judou,alphanum,halfwidth,boundary}\do{%
  \appendinterclasstoks{\class}{cjkexta}{\zhcjkextafont}
  \appendinterclasstoks{\class}{cjkextb}{\zhcjkextbfont}
  \prependinterclasstoks{cjkexta}{\class}{\zhfont}
  \prependinterclasstoks{cjkextb}{\class}{\zhfont}
}
\setinterclasstoks{cjkexta}{cjkextb}{\zhcjkextbfont}
\setinterclasstoks{cjkextb}{cjkexta}{\zhcjkextafont}
\newcount\n
\n="3400 \loop \ifnum\n<"4E00 \XeTeXcharclass\n=8 \advance\n by 1\repeat
\n="20000\loop \ifnum\n<"30000 \XeTeXcharclass\n=9 \advance\n by 1\repeat
% long fullwidth punctuations
\newclass[fwpunct]{longpunct} % … etc
\setclassnum{longpunct}{5}
\setinterclasstoks{longpunct}{longpunct}{\zhnobreak}
% derived class from halfwidth
\newclass[halfwidth]{hwpunct} % (, ., etc
\setclassnum{hwpunct}{6}

% Font settings
\@ifundefined{LaTeX}{%
  \@ifundefined{zhfont}{\font\zhfont="SimSun" at 10pt}{}
  \@ifundefined{zhpunctfont}{\font\zhpunctfont="SimSun" at 10pt}{}
  \@ifundefined{zhcjkextafont}{\def\zhcjkextafont{\message{CJK Ext-A}}}{}
  \@ifundefined{zhcjkextbfont}{\def\zhcjkextbfont{\message{CJK Ext-B}}}{}
}{%
  \RequirePackage{fontspec}
  \@ifundefined{zhfont}{\newfontfamily\zhfont[BoldFont=SimHei]{SimSun}}{}
  \@ifundefined{zhpunctfont}{\newfontfamily\zhpunctfont{SimSun}}{}
  \@ifundefined{zhcjkextafont}{\def\zhcjkextafont{\message{CJK Ext-A}}}{}
  \@ifundefined{zhcjkextbfont}{\def\zhcjkextbfont{\message{CJK Ext-B}}}{}
}

\def\zhspacing{%
  \@foreach\character\in{`：,`，,`、,`。,`．}\do{\XeTeXcharclass\character=4}
  \@foreach\character\in{`“,`‘}\do{\XeTeXcharclass\character=2}
  \@foreach\character\in{`”,`’}\do{\XeTeXcharclass\character=3}
  \@foreach\character\in{`—,`…}\do{\XeTeXcharclass\character=5}
  \@foreach\character\in{`\!,`\",`\',`\(,`\),`\,,`\-,`\.,`\:,`\;,`\<,`\>,`\?,`\[,`\],`\`,`\{,`\}}\do{\XeTeXcharclass\character=6}
  \@foreach\character\in{`℃}\do{\XeTeXcharclass\character=7}
  % clear XeTeX pre-defined toks
  \XeTeXinterchartoks 0 1 = {}
  \XeTeXinterchartoks 0 2 = {}
  \XeTeXinterchartoks 0 3 = {}
  \XeTeXinterchartoks 1 0 = {}
  \XeTeXinterchartoks 2 0 = {}
  \XeTeXinterchartoks 3 0 = {}
  \XeTeXinterchartoks 1 1 = {}
  \XeTeXinterchartoks 1 2 = {}
  \XeTeXinterchartoks 1 3 = {}
  \XeTeXinterchartoks 2 1 = {}
  \XeTeXinterchartoks 2 2 = {}
  \XeTeXinterchartoks 2 3 = {}
  \XeTeXinterchartoks 3 1 = {}
  \XeTeXinterchartoks 3 2 = {}
  \XeTeXinterchartoks 3 3 = {}
  \registerXeTeXclasstoks
  \XeTeXinterchartokenstate=1
  \parindent=2em
  \message{zhspacing installed.^^J}
}
\fi
